﻿using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
using GurLoader.Service;
using GurLoader.Service.ImgurTaskBuilder;
using GurLoader.Service.TaskExecution;
using GurLoader.Util;
using GurLoader.View;
using GurLoader.ViewModel;
using Moq;
using NUnit.Framework;

namespace GurLoaderWPF.Test.Service.TaskExecution
{
    [TestFixture]
    public class DefaultTaskExecutionServiceTests
    {
        [Test]
        public void CreateInstanceTest()
        {
            Mock<IViewBuilder> viewBuilderMock = new Mock<IViewBuilder>();
            Dispatcher d = Dispatcher.CurrentDispatcher;
            var service = new DefaultTaskExecutionService(d, viewBuilderMock.Object);

            Assert.IsNotNull(service);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CreateInstanceNullDispatcherTest()
        {
            Mock<IViewBuilder> viewBuilderMock = new Mock<IViewBuilder>();
            Dispatcher d = null;
            var service = new DefaultTaskExecutionService(d, viewBuilderMock.Object);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CreateInstanceNullViewBuilderTest()
        {
            Dispatcher d = Dispatcher.CurrentDispatcher;
            var service = new DefaultTaskExecutionService(d, null);
        }

        [Test]
        [STAThread]
        public void ExecuteTaskTest()
        {
            Mock<IViewBuilder> viewBuilderMock = new Mock<IViewBuilder>();
            Mock<ICommandManager> mockCommandManager = new Mock<ICommandManager>();
            CancellationTokenSource cts = new CancellationTokenSource();

            viewBuilderMock.Setup(x=>x.CreateMainWindow(It.IsAny<GurLoaderViewModel>(), true)).Verifiable();

            ManualResetEvent mre = new ManualResetEvent(false);

            Task<ImgurProcessResult> task = new Task<ImgurProcessResult>(() =>
            {
                mre.Set();
                return null;
            });

            Dispatcher d = Dispatcher.CurrentDispatcher;
            var service = new DefaultTaskExecutionService(d, viewBuilderMock.Object);

            Assert.IsNotNull(service);
            Progress<IDelegatingCommandProgress> progress = new Progress<IDelegatingCommandProgress>();

            service.ExecuteTask(task, progress, cts, mockCommandManager.Object);
            DispatcherUtil.DoEvents();
            bool mreSet = mre.WaitOne(1000*5);

            viewBuilderMock.Verify(x => x.CreateMainWindow(It.IsAny<GurLoaderViewModel>(), true), Times.Once);

            if (! mreSet)
                Assert.Fail("Timeout waiting for task execution.");

            mockCommandManager.VerifyAll();
        }
    }
}
